const http = require('http')
const Stream = require('stream')
const context = require('./context')
const request = require('./request')
const response = require('./response')
const EventEmitter = require('events')

class Application extends EventEmitter {

    constructor() {
        super()
        //  实现每次创建一个应用都有自己的全新上下文
        this.context = Object.create(context)
        this.request = Object.create(request)
        this.response = Object.create(response)
        this.middlewares = []
    }

    use(middleware) {
        // this.fn = fn;
        this.middlewares.push(middleware)
    }
    createContext(req, res) {
        // 这个目的是为了每次请求的时候 都拥有自己的上下文，而且自己的上下文是可以获取公共上下文声明的变量、属性
        const ctx = Object.create(this.context)
        const request = Object.create(this.request)
        const response = Object.create(this.response)
        // 几种关系
        ctx.req = req;
        ctx.request = request;
        ctx.request.req = req;

        ctx.res = res;
        ctx.response = response;
        ctx.response.res = res;

        return ctx
    }
    compose(ctx) {
        let index = -1;
        const dispatch = (i) => {
            if (index >= i) return Promise.reject(new Error('called multipe times next()'))
            index = i;
            if (this.middlewares.length === i) return Promise.resolve()
            return Promise.resolve(this.middlewares[i](ctx, () => dispatch(i + 1)))
        }
        return dispatch(0)
    }
    handleRequest = (req, res) => {
        const ctx = this.createContext(req, res)
        res.statusCode = 404;
        // this.fn(ctx)
        this.compose(ctx).then(() => {
            const _body = ctx.body
            if (_body) {
                if (typeof _body === 'string' || Buffer.isBuffer(_body)) {
                    // 如果是字符串或者buffer可以直接返回
                    return res.end(_body)
                } else if (typeof _body === 'number') {
                    return res.end(_body + '')
                } else if (_body instanceof Stream) {
                    // 可以设置成下载头 
                    // res.setHeader('Content-Type', 'application/octet-stream');
                    // 设置不识别的header 也会变成下载文件，设置对了才行
                    // res.setHeader('Content-Disposition', 'attachment;filename=FileName.txt');
                    res.setHeader('Content-Type', 'text/plain;charset=utf-8');
                    return _body.pipe(res)
                } else if (typeof _body === 'object') {
                    res.setHeader('Content-Type', 'text/plain;charset=utf-8');
                    return res.end(JSON.stringify(_body))
                }
            } else {
                res.end('Not Found')
            }
        }).catch(error => {
            this.emit('error', error)
        })

    }
    listen(...args) {
        const server = http.createServer(this.handleRequest)
        server.listen(...args)
    }

}

module.exports = Application;
// function Foo() {
//     getName = function () {
//         console.log(1);
//     };
//     return this;
// }
// Foo.getName = function () {
//     console.log(2);
// };
// Foo.prototype.getName = function () {
//     console.log(3);
// };
// var getName = function () {
//     console.log(4);
// };
// function getName() {
//     console.log(5);
// }
// Foo.getName();
// getName();
// Foo().getName();
// getName();
// new Foo.getName();
// new Foo().getName();
// new new Foo().getName();